var scrollParallax = function(){
	var settings = {},
		scrollTop = 0,
		started = false,
		paused = false;
	var	w = $(window),
		d = $(document),
		scrollDirection = 0,
		scrollTopTweened = 0;
		
	function init(opts){
		var defaults = {
			animation: null,
			maxScroll: 1000,
			tickSpeed: 30,
			scrollSpeed: 20,
			container: $('body'),
			useRAF: true,
			tweenSpeed: .3
		};
		
		settings = $.extend(defaults,opts);
		animation = settings.animation;
		
		d.on('mousewheel', wheelHandler);
		
		window.requestAnimFrame = (function(){
			if (settings.useRAF) {
				return  
				window.requestAnimationFrame       || 
				window.webkitRequestAnimationFrame || 
				window.mozRequestAnimationFrame    || 
				window.oRequestAnimationFrame      || 
				window.msRequestAnimationFrame     || 
				function( callback ){
					window.setTimeout(callback, settings.tickSpeed);
				};
			} else {
				return function( callback ){
					window.setTimeout( callback, settings.tickSpeed);
				}
			};
		})();
		
		setAnimatable();
		animationLoop();
		
		return this;
	}
	
	function wheelHandler(e, delta, deltaX, deltaY){
		if(paused) return;
		scrollTop -= delta * settings.scrollSpeed;
		if ( scrollTop < 0) scrollTop = 0;
		if (scrollTop > settings.maxScroll) 
			scrollTop = settings.maxScroll;
	}
	
	function animationLoop() {
		requestAnimFrame(animationLoop);
		if (paused)
			return;
			
		if(Math.ceil(scrollTopTweened) != Math.floor(scrollTop)){
			
			scrollTopTweened += settings.tweenSpeed * (scrollTop - scrollTopTweened);
			
			scrollDirection = scrollTop > scrollTopTweened ? 1 : -1;
			
			for (var i in animation) {
				
				var anim = animation[i];
				if (scrollTopTweened >= anim.startAt && scrollTopTweened <= anim.endAt) {
					startAnimatable( anim );
					render( anim );
				} else {
					stopAnimatable( anim );
				}
				
			}
			
			if (typeof settings.onUpdate === 'function') settings.onUpdate(scrollTopTweened);
		}
	}
	
	function render(anim){
	
		var progress = (anim.startAt - scrollTopTweened) / (anim.startAt - anim.endAt);
		progress = Math.max(0, Math.min(1, progress));
		
		var properties = {};
		
		anim.lastProgress = progress;
		
		if(anim.keyframes) {
			for ( var i = 1; i < anim.keyframes.length; i++ ) {
			
				var keyframe = anim.keyframes[i],
				lastkeyframe = anim.keyframes[ i - 1 ],
				keyframeProgress = ( lastkeyframe.position - progress ) / ( lastkeyframe.position - keyframe.position );
				
				if ( keyframeProgress >= 0 && keyframeProgress <= 1 ) {
					
					if( keyframe.onProgress && typeof keyframe.onProgress === 'function' ){
						keyframe.onProgress.call(keyframeProgress , scrollDirection);
					}
					
					for( var property in keyframe.properties ){
						
						if (property==="background-position" && keyframe.properties[property].hasOwnProperty("x")) {
							
							var startValues = keyframe.properties[property];
							var endValues = lastkeyframe.properties[property];
							var result = "";
							
							if (typeof startValues.x === "number") {
								
							} else {
								
							}
							
						} else {
							//Just tween the value otherwise
							properties[ property ] = getTweenedValue( lastkeyframe.properties[property], keyframe.properties[property], keyframeProgress, 1, keyframe.ease );
						}
						
					}
					
				}
				
			}
		}
		if (anim._elem == undefined) {
			anim._elem = $(anim.selector);
		}
		
		anim._elem.css( properties );
		// onProgress callback
		if (anim.onProgress && typeof anim.onProgress === 'function') {
			anim.onProgress.call(anim, progress );
		}
		
	}
	
	function getTweenedValue(start, end, currentTime, totalTime, tweener){
		var delta = end - start;
	    var percentComplete = currentTime/totalTime;
	    if (!tweener) tweener = TWEEN.Easing.Linear.EaseNone;
		
	    return tweener(percentComplete) * delta + start;
	}
	
	// gọi đến trước khi bắt đầu chuyển động
	function startAnimatable(anim){
		if(!anim._started){
			if(anim.onStartAnimate && typeof anim.onStartAnimate === 'function'){
				anim.onStartAnimate.call( anim, scrollDirection);
			} else {
				anim._elem.css('display', 'block');
			}
			anim._started = true;
		}
	}
	
	// render khi end sự kiện
	function stopAnimatable(anim) {
		if ( (anim._started && anim.endAt < scrollTopTweened || anim._started && anim.startAt > scrollTopTweened ) 
			|| (scrollDirection<0 && anim.lastProgress>0 && anim.startAt > scrollTopTweened)
			|| (scrollDirection>0 && anim.lastProgress<1 && anim.endAt < scrollTopTweened) 
			) {

			render( anim );
			
			if (anim.onEndAnimate && typeof anim.onEndAnimate === 'function') {
				anim.onEndAnimate.call( anim , scrollDirection );
			}
			
			anim._started = false;
		}
	}
	
	// gán giá trị properities khi bắt đầu start
	function setAnimatable() {
		for (var i in animation) {
			var anim = animation[i];

			anim.lastProgress = 0;
			if (anim._elem == undefined) {
				anim._elem = $(anim.selector);
			}

			if (typeof anim.onInit == 'function') anim.onInit.call( anim );
			
			for (var k in anim.keyframes) {
				var keyframe = anim.keyframes[k];
				if (keyframe.position == 0) {
					var nKeyframe = anim.keyframes[Number(k)+1];
					for (var property in nKeyframe.properties) {
						if (keyframe.properties[ property ] == undefined) {
							if (/left|top/.test(property)) {
								keyframe.properties[ property ] = anim._elem.position()[ property ];
							}
						}
					}
				}
				
				var bIndex = Number(k);

				while (bIndex > 0) {
					var bKeyframe = anim.keyframes[ bIndex ];

					for (var property in bKeyframe.properties) {
						if ( keyframe.properties[ property ] == undefined) {
							keyframe.properties[ property ] = bKeyframe.properties[ property ];
						}
					}

					bIndex--;
				};

				if (typeof keyframe.onInit == 'function') keyframe.onInit( anim );

			}
		
		}
		
	}
	
	// xử lý resize
	
	return {
		init: init
	}
};